﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Myotragus.Data.Registration
{
	public static class Filters
	{
		public static IEntitiesInterfacesCollection Implementing(this IEntitiesInterfacesCollection @this, Type type)
		{
			return new EntitiesInterfacesCollection { Actual = @this.Where(type.IsAssignableFrom) };
		}

		public static IEntitiesInterfacesCollection Implementing<TType>(this IEntitiesInterfacesCollection @this)
		{
			return @this.Implementing(typeof(TType));
		}

		public static IEntitiesInterfacesCollection NotImplementing(this IEntitiesInterfacesCollection @this, Type type)
		{
			return new EntitiesInterfacesCollection { Actual = @this.Where(t => !type.IsAssignableFrom(t)) };
		}

		public static IEntitiesInterfacesCollection NotImplementing<TType>(this IEntitiesInterfacesCollection @this)
		{
			return @this.NotImplementing(typeof(TType));
		}

		public static IEntitiesImplementationCollection Implementing(this IEntitiesImplementationCollection @this, Type type)
		{
			return new EntitiesImplementationCollection { Actual = @this.Where(type.IsAssignableFrom) };
		}

		public static IEntitiesImplementationCollection Implementing<TType>(this IEntitiesImplementationCollection @this)
		{
			return @this.Implementing(typeof(TType));
		}

		public static IEntitiesImplementationCollection NotImplementing(this IEntitiesImplementationCollection @this, Type type)
		{
			return new EntitiesImplementationCollection
			{
				Actual =
					@this.Where(t => !type.IsAssignableFrom(t))
			};
		}

		public static IEntitiesImplementationCollection NotImplementing<TType>(this IEntitiesImplementationCollection @this)
		{
			return @this.NotImplementing(typeof(TType));
		}

		public static IServicesImplementationCollection Except(
			this IServicesImplementationCollection @this, IEnumerable<Type> except)
		{
			return new ServicesImplementationCollection
			{
				Actual =
					((IEnumerable<Type>)@this).Except(except)
			};
		}

		public static IServicesImplementationCollection Except(this IServicesImplementationCollection @this, params Type[] except)
		{
			return @this.Except((IEnumerable<Type>)except);
		}

		public static IServicesImplementationCollection Implementing(this IServicesImplementationCollection @this, Type type)
		{
			return new ServicesImplementationCollection { Actual = @this.Where(type.IsAssignableFrom) };
		}

		public static IServicesImplementationCollection Implementing<TType>(this IServicesImplementationCollection @this)
		{
			return @this.Implementing(typeof(TType));
		}

		public static IServicesImplementationCollection NotImplementing(this IServicesImplementationCollection @this, Type type)
		{
			return new ServicesImplementationCollection
			{
				Actual =
					@this.Where(t => !type.IsAssignableFrom(t))
			};
		}

		public static IServicesImplementationCollection NotImplementing<TType>(this IServicesImplementationCollection @this)
		{
			return @this.NotImplementing(typeof(TType));
		}
	}
}